﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.NetworkInformation;
using System.Threading.Tasks;

using Newtonsoft.Json.Linq;

namespace AutoTranslate.Translators {
    public enum Engine {
        Baidu,
        Google,
        Youdao,
        Excite,
        Iciba,
    }

    public interface ITranslator {
        Engine Engine { get; }
        string Name { get; }
        string Hint { get; }
        string Host { get; }
        int Order { get; }
        Task<PingReply> Ping();
        Task<string> Translate(string text);
    }

    public abstract class Translator : ITranslator {
        static Translator() {
            Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            Client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("zh-CN"));
            Client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("zh"));
        }

        protected static readonly HttpClient Client = new HttpClient();

        public abstract Engine Engine { get; }

        public abstract string Name { get; }

        public virtual string Hint { get { return null; } }

        public virtual int Order { get { return 0; } }

        public virtual Task<PingReply> Ping() {
            pingSender.SendAsyncCancel();
            return pingSender.SendPingAsync(Host);
        }

        public abstract string Host { get; }

        public abstract Task<string> Translate(string text);

        protected Ping pingSender = new Ping();
    }

    public sealed class BaiduFanyi : Translator {
        public override Engine Engine {
            get { return Engine.Baidu; }
        }

        public override string Name { get { return "百度翻译"; } }

        public override string Hint { get { return "速度、准确度都不错，推荐使用"; } }

        public override int Order { get { return -1; } }

        public override string Host {
            get { return "fanyi.baidu.com"; }
        }

        public override async Task<string> Translate(string text) {
            Client.CancelPendingRequests();

            var postData = new Dictionary<string, string> {
                    {"ie", "utf-8"},
                    {"source", "txt"},
                    {"from", "jp"},
                    {"to", "zh"},
                    {"query", text}
                };
            using (var content = new FormUrlEncodedContent(postData)) {
                var response = await Client.PostAsync("http://fanyi.baidu.com/transcontent", content);
                var responseText = await response.Content.ReadAsStringAsync();
                return (string)JObject.Parse(responseText)["data"][0]["dst"];
            }
        }
    }

    public sealed class GoogleTranslate : Translator {
        public override Engine Engine {
            get { return Engine.Google; }
        }

        public override string Name { get { return "谷歌翻译"; } }

        public override string Host {
            get { return "translate.google.com"; }
        }

        public override async Task<string> Translate(string text) {
            Client.CancelPendingRequests();

            var postData = new Dictionary<string, string> {
                    {"ie", "utf-8"},
                    {"oe", "utf-8"},
                    {"client", "t"},
                    {"sl", "jp"},
                    {"tl", "zh-CN"},
                    {"q", text}
                };
            using (var content = new FormUrlEncodedContent(postData)) {
                var response = await Client.PostAsync("http://translate.google.cn/translate_a/t", content);
                var responseText = await response.Content.ReadAsStringAsync();
                return (string)JArray.Parse(responseText)[0][0][0];
            }
        }
    }

    public sealed class YoudaoFanyi : Translator {
        public override Engine Engine {
            get { return Engine.Youdao; }
        }

        public override string Name { get { return "有道翻译"; } }

        public override string Host {
            get { return "fanyi.youdao.com"; }
        }

        public override async Task<string> Translate(string text) {
            Client.CancelPendingRequests();

            var postData = new Dictionary<string, string> {
                    {"ue", "UTF-8"},
                    {"doctype", "json"},
                    {"keyfrom", "fanyi.web"},
                    {"type", "JA2ZH_CN"},
                    {"i", text}
                };
            using (var content = new FormUrlEncodedContent(postData)) {
                var response = await Client.PostAsync("http://fanyi.youdao.com/translate", content);
                var responseText = await response.Content.ReadAsStringAsync();
                return (string)JObject.Parse(responseText)["translateResult"][0][0]["tgt"];
            }
        }
    }

    public sealed class IcibaFanyi : Translator {
        public override Engine Engine {
            get { return Engine.Iciba; }
        }

        public override string Name { get { return "iCIBA翻译"; } }

        public override string Host {
            get { return "fy.iciba.com"; }
        }

        public override async Task<string> Translate(string text) {
            Client.CancelPendingRequests();

            var postData = new Dictionary<string, string> {
                    {"type", "jp-zh"},
                    {"q", text}
                };
            using (var content = new FormUrlEncodedContent(postData)) {
                var response = await Client.PostAsync("http://fy.iciba.com/api.php", content);
                var responseText = await response.Content.ReadAsStringAsync();
                return (string)JObject.Parse(responseText)["ret"];
            }
        }
    }

#if false // Doesn't work yet
    public sealed class ExciteHonyaku : Translator {
        public override Engine Engine {
            get { return Engine.Excite; }
        }

        public override string Name { get { return "excite翻訳"; } }

        public override string Hint { get { return "来自日站的翻译引擎，准确度较高，但速度慢"; } }
    
        public override string Host {
            get { return "www.excite.co.jp"; }
        }

        public override async Task<string> Translate(string text) {
            Client.CancelPendingRequests();

            var parameters = new Dictionary<string, string> {
                    {"mode", "detection"},
                    {"fmt", "json"},
                    {"target_langs", "ja,zh-cn,zh-tw"},
                    {"text", text}
                };
            var baseUri = new UriBuilder("http://www.excite.co.jp/world/auto/proxy") {
                Query = string.Join("&", parameters.Select(param => string.Format("{0}={1}", param.Key, param.Value)))
            };
            var response = await Client.GetAsync(baseUri.ToString());
            var responseText = await response.Content.ReadAsStringAsync();
            return (string)JObject.Parse(responseText)["text"];
        }
    }
#endif
}
